#!/usr/bin/python3
# -*- coding: utf-8 -*-

import os
import collections
import threading

try:
    import Tkinter as tk  # Python 2
except ImportError:
    import tkinter as tk  # Python 3


diskusage_namedtuple = collections.namedtuple('usage', 'path total used free')

if hasattr(os, 'statvfs'):  # POSIX
    def disk_usage(path):
        st = os.statvfs(path)
        free = st.f_bavail * st.f_frsize
        total = st.f_blocks * st.f_frsize
        used = (st.f_blocks - st.f_bfree) * st.f_frsize
        return diskusage_namedtuple(path, total, used, free)

elif os.name == 'nt':       # Windows
    import ctypes
    import sys

    def disk_usage(path):
        _, total, free = ctypes.c_ulonglong(), ctypes.c_ulonglong(), \
                           ctypes.c_ulonglong()
        if sys.version_info >= (3,) or isinstance(path, bytes):  # isinstance(path, unicode):
            path = path.decode('ascii')
            fun = ctypes.windll.kernel32.GetDiskFreeSpaceExW
        else:
            fun = ctypes.windll.kernel32.GetDiskFreeSpaceExA
        ret = fun(path, ctypes.byref(_), ctypes.byref(total), ctypes.byref(free))
        if ret == 0:
            raise ctypes.WinError()
        used = total.value - free.value
        return diskusage_namedtuple(path, total.value, used, free.value)
else:
    raise NotImplementedError("platform not supported")


def hsize(size, maxlen=5):
    __symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
    idx = 0
    if size < 1000.0:
        return str(size) + __symbols[idx]

    size = float(size)
    while size >= 1000.0:
        size /= 1024.0
        idx += 1

    if int(size) < 10: p1 = 1
    elif int(size) < 100: p1 = 2
    else: p1 = 3
    return '%*.*f %s' % (p1, maxlen - p1, size, __symbols[idx])


class MyTimer(object):
    def __init__(self, interval, function, *args, **kwargs):
        self._timer = None
        self.interval = interval
        self.function = function
        self.args = args
        self.kwargs = kwargs
        self.is_running = False
        self.start()

    def _run(self):
        self.is_running = False
        self.start()
        self.function(*self.args, **self.kwargs)

    def start(self):
        if not self.is_running:
            self._timer = threading.Timer(self.interval, self._run)
            self._timer.start()
            self.is_running = True

    def stop(self):
        self._timer.cancel()
        self.is_running = False


class HDMon(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.overrideredirect(True)

        self.geo = self.winfo_geometry()
        self.x, self.y = self.winfo_x(), self.winfo_y()
        self.width, self.height = self.winfo_width(), self.winfo_height()
        self.mx = None
        self.my = None
        self.caption_frame = tk.Frame(self, height=18)  # , height=20)
        self.caption_frame.pack(side=tk.TOP, fill=tk.X, expand=False)

        self.caption_text = tk.StringVar()
        self.caption = tk.Label(self.caption_frame, text="Title", bg="#888", textvariable=self.caption_text)
        # self.caption.pack(in_=self.caption_frame, side="left", fill="both", expand=True)
        self.caption.place(x=0, y=0, width=self.width-20, height=18)
        self.caption_text.set('My Media Player')
        self.caption.bind("<ButtonPress-1>", self.on_start_move)
        self.caption.bind("<ButtonRelease-1>", self.on_stop_move)
        self.caption.bind("<B1-Motion>", self.on_motion)

        self.close_btn = tk.Button(self.caption_frame, text='X',
                                   # image=img, compound="left",
                                   command=self.exit)
        # self.close_btn.pack(side='right', fill='y')
        self.close_btn.place(x=self.width-19, y=0, width=18, height=18)

        self.disks = []

        self.timer = MyTimer(0.5, self.update_info)

    def add_disk(self, disk):
        self.disks.append(diskusage_namedtuple(disk, 2, 1, 1))

    def update_info(self):
        if self.geo == self.winfo_geometry():
            pass
        else:
            self.geo = self.winfo_geometry()
            self.x, self.y = self.winfo_x(), self.winfo_y()
            self.width, self.height = self.winfo_width(), self.winfo_height()
            print(self.geo)

            # self.close_btn.place(x=self.width-20, y=1, width=20, height=18)
            self.caption.place(x=0, y=0, width=self.width-22, height=18)
            self.close_btn.place(x=self.width-21, y=0, width=20, height=18)
        for disk in self.disks:
            disk = disk_usage(disk.path)
            print("%-12s%8s/%8s" % (disk.path, hsize(disk.free), hsize(disk.total)))

    def on_start_move(self, event):
        self.mx = event.x
        self.my = event.y

    def on_stop_move(self, event):
        self.mx = None
        self.my = None

    def on_motion(self, event):
        deltax = event.x - self.mx
        deltay = event.y - self.my
        x = self.winfo_x() + deltax
        y = self.winfo_y() + deltay
        self.geometry("+%s+%s" % (x, y))

    def exit(self, event=None):
        self.timer.stop()
        quit()

if __name__ == "__main__":
    app = HDMon()
    app.title("HDD Mon")
    app.geometry("100x18")
    app.add_disk('/')
    app.add_disk('/media/home')
    app.mainloop()
    app.exit()
